package com.wy.component.ldap;

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Hashtable;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.naming.Context;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.directory.Attribute;
import javax.naming.directory.Attributes;
import javax.naming.directory.DirContext;
import javax.naming.directory.InitialDirContext;
import javax.naming.directory.SearchControls;
import javax.naming.directory.SearchResult;

import org.apache.axis.encoding.Base64;

public class LdapHelperNew {
	private static DirContext ctx = null;

	@SuppressWarnings({ "rawtypes", "unchecked" })
	private static DirContext getCtx() {
		String root = "dc=portal,dc=zcmu,dc=edu,dc=cn";
		String password = "secret";
		
		Hashtable env = new Hashtable();
		env.put(Context.INITIAL_CONTEXT_FACTORY,"com.sun.jndi.ldap.LdapCtxFactory");
		env.put(Context.PROVIDER_URL, "ldap://192.168.21.38:389/" + root);
		env.put(Context.SECURITY_AUTHENTICATION, "simple");
		env.put(Context.SECURITY_PRINCIPAL, "cn=Manager," + root);
		env.put(Context.SECURITY_CREDENTIALS, password);
		try {
			ctx = new InitialDirContext(env);
//			System.out.println("认证成功");
		} catch (javax.naming.AuthenticationException e) {
			System.out.println("Authentication faild: " + e.toString());
		} catch (Exception e) {
			System.out.println("Something wrong while authenticating: "
					+ e.toString());
		}
		return ctx;
	}

	public static void closeCtx() {
		try {
			ctx.close();
		} catch (NamingException ex) {
			Logger.getLogger(LdapHelperNew.class.getName()).log(Level.SEVERE,
					null, ex);
		}
	}

	public static String authenticate(String user, String inputPwd)throws NoSuchAlgorithmException {
		String userType = "student";
		String userName ="";
		boolean valide = false;
		DirContext ctx = null;
		try {
			ctx = LdapHelperNew.getCtx();
			SearchControls constraints = new SearchControls();
			constraints.setSearchScope(SearchControls.SUBTREE_SCOPE);
			NamingEnumeration en = ctx.search("", "uid=" + user, constraints); // 查询所有用户
			while (en != null && en.hasMoreElements()) {
				Object obj = en.nextElement();
				if (obj instanceof SearchResult) {
					SearchResult si = (SearchResult) obj;
//					System.out.println("name:   " + si.getName());
					if(si.getName().indexOf("ou=teacher")!= -1){
						userType = "teacher";
					}
					Attributes attrs = si.getAttributes();
					if (attrs == null) {
//						System.out.println("No attributes");
					} else {						
						Attribute attr = attrs.get("userPassword");
						Object o = attr.get();
						byte[] s = (byte[]) o;
						String ldapUserPwd = new String(s);
						attr = attrs.get("cn");
						o = attr.get();
						userName = (String)o; 
						if(inputPwd.equals(ldapUserPwd)){
							valide=true;
						}
					}
				} else {
//					System.out.println(obj);
				}
//				System.out.println();
			}
			ctx.close();
		} catch (NamingException ex) {
			try {
				if (ctx != null) {
					ctx.close();
				}
			} catch (NamingException namingException) {
				namingException.printStackTrace();
			}
			Logger.getLogger(LdapHelperNew.class.getName()).log(Level.SEVERE,
					null, ex);
		}
		if (valide) {
			return userType+","+userName;
		} else {
			return "false";
		}
	}

	@SuppressWarnings(value = "unchecked")
	public static boolean verifySHA(String ldappw, String inputpw)
			throws NoSuchAlgorithmException {

		// MessageDigest 提供了消息摘要算法，如 MD5 或 SHA，的功能，这里LDAP使用的是SHA-1
		MessageDigest md = MessageDigest.getInstance("MD5");

		// 取出加密字符
		if (ldappw.startsWith("{SSHA}")) {
			ldappw = ldappw.substring(6);
		} else if (ldappw.startsWith("{SHA}")) {
			ldappw = ldappw.substring(5);
		} else if (ldappw.startsWith("{MD5}")) {
			ldappw = ldappw.substring(5);
		}

		// 解码BASE64
		byte[] ldappwbyte = Base64.decode(ldappw);
		byte[] shacode;
		byte[] salt;

		// 前20位是SHA-1加密段，20位后是最初加密时的随机明文
		if (ldappwbyte.length <= 20) {
			shacode = ldappwbyte;
			salt = new byte[0];
		} else {
			shacode = new byte[20];
			salt = new byte[ldappwbyte.length - 20];
			System.arraycopy(ldappwbyte, 0, shacode, 0, 20);
			System.arraycopy(ldappwbyte, 20, salt, 0, salt.length);
		}

		// 把用户输入的密码添加到摘要计算信息
		md.update(inputpw.getBytes());
		// 把随机明文添加到摘要计算信息
		md.update(salt);

		// 按SSHA把当前用户密码进行计算
		byte[] inputpwbyte = md.digest();

		// 返回校验结果
		return MessageDigest.isEqual(shacode, inputpwbyte);
	}
	
	@SuppressWarnings("static-access")
	public static void main(String[] args) throws NoSuchAlgorithmException {

	}
	
	public static final String bytesToHexString(byte[] bArray) {
		StringBuffer sb = new StringBuffer(bArray.length);
		String sTemp;
		for (int i = 0; i < bArray.length; i++) {
			sTemp = Integer.toHexString(0xFF & bArray[i]);
			if (sTemp.length() < 2)
				sb.append(0);
			sb.append(sTemp.toUpperCase());
		}
		return sb.toString();
	}
}
